﻿#region copyright
/*
 * Author: Jan Vilimek: jan (at) vilimek (dot) cz
 * If you use any code from this program/library, please include above line
 * 
 */
#endregion

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace pdb2mobiGUI
{

	//[StructLayout(LayoutKind.Sequential)]
	class PDBHeader
	{
		public PDBHeader()
		{
			this.Reset();
		}

		//[FieldOffset(0)]
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
		byte[] databaseName;						// 32 Bytes

		//[FieldOffset(32)]
		[MarshalAs(UnmanagedType.U2, SizeConst = 2)]
		UInt16 fileAttributes;						// 2 Bytes

		//[FieldOffset(34)]
		[MarshalAs(UnmanagedType.U2, SizeConst = 2)]
		UInt16 version;							// 2 Bytes

		//[FieldOffset(36)]
		[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
		UInt32 creationDate;						// 4 Bytes

		//[FieldOffset(40)]
		[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
		UInt32 modificationDate;					// 4 Bytes

		//[FieldOffset(44)]
		[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
		UInt32 lastBackupDate;						// 4 Bytes

		//[FieldOffset(48)]
		[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
		UInt32 modification;						// 4 Bytes

		//[FieldOffset(52)]
		[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
		UInt32 appInfoID;						// 4 Bytes

		//[FieldOffset(56)]
		[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
		UInt32 sortInfoID;						// 4 Bytes

		//[FieldOffset(60)]
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
		byte[] dbType;							// 4 Bytes

		//[FieldOffset(64)]
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
		byte[] creatorID;						// 4 Bytes

		//[FieldOffset(68)]
		[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
		UInt32 uniqueID;						// 4 Bytes

		//[FieldOffset(72)]
		[MarshalAs(UnmanagedType.U4, SizeConst = 4)]
		UInt32 nextRecordID;						// 4 Bytes

		//[FieldOffset(76)]
		[MarshalAs(UnmanagedType.U2, SizeConst = 2)]
		UInt16 numRecords;						// 2 Bytes

		#region Properties
		public UInt16 NumRecords
		{
			set
			{
				numRecords = value;
			}
			get
			{
				return numRecords;
			}
		}
		public DateTime CreationDate
		{
			set
			{
				TimeSpan ts = DateTime.Now - value;
				creationDate = (UInt32)ts.TotalSeconds;
			}
		}
		public DateTime ModificationDate
		{
			set
			{
				TimeSpan ts = DateTime.Now - value;
				modificationDate = (UInt32)ts.TotalSeconds;
			}
		}
		public DateTime LastBackupDate
		{
			set
			{
				TimeSpan ts = DateTime.Now - value;
				lastBackupDate = (UInt32)ts.TotalSeconds;
			}
		}

		public string CreatorID
		{
			set
			{
				if (value.Length == 4)
				{
					creatorID = Encoding.GetEncoding(CodePage).GetBytes(value);
				}
				else
				{
					throw new InvalidOperationException("Creator ID is invalid (must be 4 charactors)"); ;
				}
			}
			get
			{
				return Encoding.GetEncoding(CodePage).GetString(creatorID);
			}
		}

		public string DataBaseName
		{
			set
			{
				if (value.Length <= 32)
				{
					databaseName = Encoding.GetEncoding(CodePage).GetBytes(value);
				}
				else
				{

					throw new InvalidOperationException("Database Name Exceeds 32 Charactors"); ;
				}
			}
			get
			{
				var length = databaseName.Length;
				for (int i = 0; i < length; i++)
					if (databaseName[i] == 0)
					{
						length = i + 1;
						break;
					}
				return Encoding.GetEncoding(CodePage).GetString(databaseName, 0, length);
			}
		}

		public string DbType
		{
			set
			{
				if (value.Length <= 32)
				{
					dbType = Encoding.GetEncoding(CodePage).GetBytes(value);
				}
				else
				{

					throw new InvalidOperationException("Database Name Exceeds 32 Charactors"); ;
				}
			}
			get
			{
				return Encoding.GetEncoding(CodePage).GetString(dbType);
			}
		}

		public int SizeOfStructure
		{ get { return 78; } }// Marshal.SizeOf(typeof(PDBHeader2)); } }

		#endregion

		#region Functions

		public void Reset()
		{
			databaseName = new byte[32] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
			fileAttributes = 0X0008;
			version = 0;

			TimeSpan ts = DateTime.Now - DateTime.Parse("01-01-1904");
			creationDate = (UInt32)ts.TotalSeconds;
			modificationDate = (UInt32)ts.TotalSeconds;
			lastBackupDate = (UInt32)ts.TotalSeconds;
			modification = 0;
			appInfoID = 0;
			sortInfoID = 0;
			dbType = new byte[] { (byte)'d', (byte)'a', (byte)'t', (byte)'a' };
			creatorID = new byte[] { (byte)'U', (byte)'N', (byte)'K', (byte)'N' };
			uniqueID = 0;
			nextRecordID = 0;
			numRecords = 0;
		}

		#endregion

		public static int CodePage = 1250;

		internal bool Read(System.IO.BinaryReader br)
		{
			var tSize = this.SizeOfStructure;// Marshal.SizeOf(typeof(PDBHeader));
			var buff = br.ReadBytes(tSize);
			if (buff.Length < tSize)
				return false;	//wrong file?

			var offset = 0;
			Utils.Copy(buff, databaseName, ref offset, 32);

			fileAttributes = Utils.ConvertBigEndianUInt16(buff, ref offset);
			version = Utils.ConvertBigEndianUInt16(buff, ref offset);
			creationDate = Utils.ConvertBigEndianUInt32(buff, ref offset);
			modificationDate = Utils.ConvertBigEndianUInt32(buff, ref offset);
			lastBackupDate = Utils.ConvertBigEndianUInt32(buff, ref offset);
			modification = Utils.ConvertBigEndianUInt32(buff, ref offset);
			appInfoID = Utils.ConvertBigEndianUInt32(buff, ref offset);
			sortInfoID = Utils.ConvertBigEndianUInt32(buff, ref offset);
			Utils.Copy(buff, dbType, ref offset, 4);
			Utils.Copy(buff, creatorID, ref offset, 4);
			uniqueID = Utils.ConvertBigEndianUInt32(buff, ref offset);
			nextRecordID = Utils.ConvertBigEndianUInt32(buff, ref offset);
			numRecords = Utils.ConvertBigEndianUInt16(buff, ref offset);
			return true;
		}
	}
}
